package com.pengtu.entity.app;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;

import com.google.common.collect.Sets;
import com.pengtu.entity.IdEntity;
import com.pengtu.utils.reflection.ConvertUtils;

/**
 * 用户.
 * 
 * 使用JPA annotation定义ORM关系. 使用Hibernate annotation定义JPA 1.0未覆盖的部分.
 * 
 * @author calvin
 */
@Entity
// 表名与类名不相同时重新定义表名.
@Table(name = "T_APP_USER")
// 默认的缓存策略.
@JsonAutoDetect 
@JsonIgnoreProperties (value = { "roleList" , "organization","password" ,"authorities"}) 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User extends IdEntity implements UserDetails,
		org.jbpm.api.identity.User {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String userName; // 用户名
	private String password; // 密码
	private Date latestLoginTime; // 上次登录时间
	private String name; // 姓名
	private String sex; // 性别
	private String age; // 年龄
	private String specialty; // 专业
	private String dutyName; // 职称
	private String email; // 邮箱地址
	private String degree; // 学历
	private String phone; // 固定电话
	private String mobilePhone; // 手机
	private String remark; // 备注
	private Set<Role> roleList = Sets.newHashSet(); // 角色信息
	private Set<UserDepartment> userDepartmentList = Sets
			.newTreeSet(new Comparator<UserDepartment>() {
				public int compare(UserDepartment o1, UserDepartment o2) {
					return o1.getEndDate().compareTo(o2.getEndDate());
				};
			}); // 用户部门信息
	private Organization organization; // 所属单位信息
	private String expired;
	private String locked;
	private String credexpired;
	private String enable;

	@Column(nullable = false, unique = true, length = 50, name = "USERNAME")
	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
    @Transient
	public String getOrgName () {
    	 if(this.getOrganization() != null) {
		return this.getOrganization().getOrgName();
    	 }
    	 return null;
		
	}
	@Column(nullable = false, length = 255)
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name = "LATESTLOGINTIME")
	public Date getLatestLoginTime() {
		return latestLoginTime;
	}

	public void setLatestLoginTime(Date latestLoginTime) {
		this.latestLoginTime = latestLoginTime;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getSpecialty() {
		return specialty;
	}

	public void setSpecialty(String specialty) {
		this.specialty = specialty;
	}

	@Column(name = "DUTYNAME")
	public String getDutyName() {
		return dutyName;
	}

	public void setDutyName(String dutyName) {
		this.dutyName = dutyName;
	}

	@Column(nullable = false, unique = true)
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Column(name = "MOBILEPHONE")
	public String getMobilePhone() {
		return mobilePhone;
	}

	public void setMobilePhone(String mobilePhone) {
		this.mobilePhone = mobilePhone;
	}

	@Column(name = "REMARK")
	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	@Column(name = "EXPIRED")
	public String getExpired() {
		return expired;
	}

	public void setExpired(String expired) {
		this.expired = expired;
	}

	@Column(name = "LOCKED")
	public String getLocked() {
		return locked;
	}

	public void setLocked(String locked) {
		this.locked = locked;
	}

	@Column(name = "CREDEXPIRED")
	public String getCredexpired() {
		return credexpired;
	}

	public void setCredexpired(String credexpired) {
		this.credexpired = credexpired;
	}

	@Column(name = "ENABLE")
	public String getEnable() {
		return enable;
	}

	public void setEnable(String enable) {
		this.enable = enable;
	}

	// 多对多定义
	@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
	// 中间表定义,表名采用默认命名规则
	@JoinTable(name = "R_APP_USERROLERELATION", joinColumns = { @JoinColumn(name = "USERID", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "ROLEID", referencedColumnName = "id") })
	// Fecth策略定义
	@Fetch(FetchMode.SUBSELECT)
	// 集合按id排序.
	@OrderBy("id")
	// 集合中对象id的缓存.
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	public Set<Role> getRoleList() {
		return roleList;
	}
	

	public void setRoleList(Set<Role> roleList) {
		this.roleList = roleList;
	}
	
	public void addRole(Role role) {
		this.roleList.add(role);
	}

	@OneToMany(mappedBy = "user", fetch = FetchType.EAGER,cascade = CascadeType.PERSIST)
	public Set<UserDepartment> getUserDepartmentList() {
		return userDepartmentList;
	}

	public void setUserDepartmentList(Set<UserDepartment> userDepartmentList) {
		this.userDepartmentList = userDepartmentList;
	}

	@ManyToOne(targetEntity = Organization.class, fetch = FetchType.EAGER,cascade = { CascadeType.PERSIST})
	@JoinColumn(name = "ORGID")
	public Organization getOrganization() {
		return organization;
	}

	public void setOrganization(Organization organization) {
		this.organization = organization;
	}

	/**
	 * 用户拥有的角色名称字符串, 多个角色名称用','分隔.
	 */
	// 非持久化属性.
	@Transient
	public String getRoleNames() {
		return ConvertUtils.convertElementPropertyToString(roleList,
				"roleName", ", ");
	}

	/**
	 * 用户拥有的角色id字符串, 多个角色id用','分隔.
	 */
	// 非持久化属性.
	@Transient
	@SuppressWarnings("unchecked")
	public List<String> getRoleIds() {
		return ConvertUtils.convertElementPropertyToList(roleList, "id");
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

	// public static void main(String[] args) {
	// System.out.println(System.getProperty("java.io.tmpdir"));
	// }
	@Transient
	@Override
	public Collection<GrantedAuthority> getAuthorities() {
		List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
		for (Role role : roleList) {
			for (Authority authority : role.getAuthorityList()) {
				authList.add(new GrantedAuthorityImpl(authority
						.getPrefixedName()));
			}
		}
		return authList;
	}

	@Transient
	@Override
	public String getUsername() {
		return userName;
	}

	@Transient
	@Override
	public boolean isAccountNonExpired() {
		return "0".equals(expired) ? true : false;
	}

	@Transient
	@Override
	public boolean isAccountNonLocked() {
		return "0".equals(locked) ? true : false;
	}

	@Transient
	@Override
	public boolean isCredentialsNonExpired() {
		return "0".equals(credexpired) ? true : false;
	}

	@Transient
	@Override
	public boolean isEnabled() {
		return "1".equals(enable) ? true : false;
	}

	@Transient
	@Override
	public String getGivenName() {
		// TODO Auto-generated method stub
		return name;
	}

	@Transient
	@Override
	public String getFamilyName() {
		// TODO Auto-generated method stub
		return name;
	}

	@Transient
	@Override
	public String getBusinessEmail() {
		return email;
	}
	
	@Column(name="DEGREE")
	public String getDegree() {
		return degree;
	}

	public void setDegree(String degree) {
		this.degree = degree;
	}
    @Column(name="PHONE")
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

}
